#include "Map.h"
#include "TileNode.h"

namespace pathfinding
{
	Map::Map()
	{

	}

	Map::~Map()
	{

	}

	pathfinding::MapTile Map::getTile( int x, int y ) const
	{
		return *getTilePtr(x, y);
	}

	void Map::setRect( const IntRect& rect )
	{
		_rect = rect;

		int pxsize = rect.size.width + rect.origin.x;
		int nxsize = rect.size.width - pxsize;
		int pysize = rect.size.height + rect.origin.y;
		int nysize = rect.size.height - pysize;

		// ++
		_map[0] = new PMapTile[pxsize];
		for (int i = 0; i < pxsize; ++i)
			_map[0][i] = new MapTile[pysize];

		//+-
		_map[1] = new PMapTile[pxsize];
		for (int i = 0; i < pxsize; ++i)
			_map[1][i] = new MapTile[nysize];

		//-+
		_map[2] = new PMapTile[nxsize];
		for (int i = 0; i < nxsize; ++i)
			_map[2][i] = new MapTile[pysize];

		//--
		_map[3] = new PMapTile[nxsize];
		for (int i = 0; i < pxsize; ++i)
			_map[3][i] = new MapTile[nysize];
	}

	void Map::setTileType( int x, int y, TileType tileType )
	{
		MapTile* tile = getTilePtr(x, y);
		tile->type = tileType;
	}

	MapTile* Map::getTilePtr( int x, int y ) const
	{
		if (x >= 0)
		{
			if (y >= 0)
			{
				return _map[0][x] + y;
			}
			else
			{
				return _map[1][x] + (-1 - y);
			}
		}
		else
		{
			if (y >= 0)
			{
				return _map[2][-1 - x] + y;
			}
			else
			{
				return _map[3][-1 - x] + (-1 - y);
			}
		}
	}

	const IntRect& Map::getRect() const
	{
		return _rect;
	}

	bool Map::isPassable( int x, int y ) const
	{
		//static const TileType ground = TileType::Road | TileType::Field;
		return getTilePtr(x, y)->type == TileType::Road;
	}

	bool Map::findPath( const IntPoint& start, const IntPoint& end, std::vector<IntPoint>* path ) 
	{
		AStarSearch<TileNode> astarsearch;

		TileNode nodeStart(this, start.x, start.y);

		// Define the goal state
		TileNode nodeEnd(this, end.x, end.y);

		// Set Start and goal states
		astarsearch.SetStartAndGoalStates( nodeStart, nodeEnd );

		unsigned int SearchState;

		unsigned int SearchSteps = 0;
		path->clear();
		do
		{
			SearchState = astarsearch.SearchStep();

			SearchSteps++;
		}
		while( SearchState == AStarSearch<TileType>::SEARCH_STATE_SEARCHING );

		if( SearchState == AStarSearch<TileNode>::SEARCH_STATE_SUCCEEDED )
		{

			TileNode *node = astarsearch.GetSolutionStart();
			int steps = 0;

			for( ;; )
			{
				node = astarsearch.GetSolutionNext();


				if( !node )
				{
					break;
				}

				path->push_back(node->getTileCoords());

				steps ++;

			};

			node = astarsearch.GetSolutionEnd();
		}
		return !path->empty();
	}
}

